package com.tbit.common.entity.vo;

import lombok.Data;
import lombok.experimental.Accessors;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 运营报表-新-响应VO
 *
 * @author: qiu.longjie
 * @create: 2025-05-08
 */
@Data
@Accessors(chain = true)
public class OperationReportRespVo {

    /**
     * 车辆总数
     */
    private Integer totalMachine;

    /**
     * 已投放车辆数
     */
    private Integer putInTotalMachine;

    /**
     * 可运营车辆数
     */
    private Integer operationalMachine;

    /**
     * 不可运营车辆数
     */
    private Integer unOperationalMachine;

    /**
     * 故障车辆数
     */
    private Integer faultMachine;

    /**
     * 订单车辆数
     */
    private Integer orderMachine;

    /**
     * 有效订单车辆数
     */
    private Integer validOrderMachine;

    /**
     * 车辆投放率
     */
    private Double machinePutInRate;

    /**
     * 车辆可用率
     */
    private Double machineAvailableRate;

    /**
     * 车辆故障率
     */
    private Double machineFaultRate;

    /**
     * 车辆骑行率
     */
    private Double machineRidingRate;

    /**
     * 车辆有效骑行率
     */
    private Double machineValidRidingRate;

    /**
     * 3天无订单车辆数
     */
    private Integer threeDaysNoOrderMachine;

    /**
     * 7天无订单车辆数
     */
    private Integer sevenDaysNoOrderMachine;

    /**
     * 15天无订单车辆数
     */
    private Integer fifteenDaysNoOrderMachine;

    /**
     * 3天无订单车辆率
     */
    private Double threeDaysNoOrderRate;

    /**
     * 7天无订单车辆率
     */
    private Double sevenDaysNoOrderRate;

    /**
     * 15天无订单车辆率
     */
    private Double fifteenDaysNoOrderRate;

    /**
     * 应收订单金额
     */
    private Double totalOrderAmount;

    /**
     * 应收订单数
     */
    private Integer totalOrderCount;

    /**
     * 实收订单金额
     */
    private Double totalReceiptOrderAmount;

    /**
     * 实收订单数
     */
    private Integer totalReceiptOrderCount;

    /**
     * 退款金额
     */
    private Double refundAmount;

    /**
     * 退款订单数
     */
    private Integer refundOrderCount;

    /**
     * 骑行卡收入金额
     */
    private Double ridingCardIncomeAmount;

    /**
     * 骑行卡收入订单数
     */
    private Integer ridingCardIncomeOrderCount;

    /**
     * 期末总预存款金额
     */
    private Double totalPreDepositAmount;

    /**
     * 应收车均收益
     */
    private Double totalMachineAgv;

    /**
     * 实收车均收益
     */
    private Double totalReceiptMachineAgv;

    /**
     * 应收车均单量
     */
    private Double totalOrderPerMachine;

    /**
     * 实收车均单量
     */
    private Double totalReceiptOrderPerMachine;

    /**
     * 应收车均里程
     */
    private Double totalDistancePerMachine;

    /**
     * 实收车均里程
     */
    private Double totalReceiptDistancePerMachine;

    /**
     * 应收车均时长
     */
    private Double totalTimePerMachine;

    /**
     * 实收车均时长
     */
    private Double totalReceiptTimePerMachine;

    /**
     * 总用户数
     */
    private Integer totalUserCount;

    /**
     * 新增用户数
     */
    private Integer newUserCount;

    /**
     * 骑行用户数
     */
    private Integer ridingUserCount;

    /**
     * 3天未骑行用户数
     */
    private Integer threeDaysNoRidingUserCount;

    /**
     * 7天未骑行用户数
     */
    private Integer sevenDaysNoRidingUserCount;

    /**
     * 15天未骑行用户数
     */
    private Integer fifteenDaysNoRidingUserCount;

    /**
     * 新用户7日留存率
     */
    private Double newUserSevenDayRetentionRate;

    /**
     * 总扫码次数
     */
    private Integer totalScanCodeCount;

    /**
     * 总开锁次数
     */
    private Integer totalUnlockCount;

    /**
     * 开锁成功次数
     */
    private Integer successUnlockCount;

    /**
     * 有效骑行次数
     */
    private Integer validOrderCount;

    /**
     * 骑行失败次数
     */
    private Integer failUnlockCount;

    /**
     * 丢单次数
     */
    private Integer lostOrderCount;

    /**
     * 总换电次数
     */
    private Integer totalPowerChangeCount;

    /**
     * 总挪车次数
     */
    private Integer totalMoveCount;

    /**
     * 总调度次数
     */
    private Integer totalDispatchCount;

    /**
     * 总维修次数
     */
    private Integer totalRepairCount;

    /**
     * 换电有效率
     */
    private Double powerChangeEfficiencyRate;

    /**
     * 挪车完成率
     */
    private Double moveCompleteRate;

    /**
     * 调度有效率
     */
    private Double dispatchEfficiencyRate;

    /**
     * 维修完成率
     */
    private Double repairCompleteRate;

    /**
     * 调度后12小时成单率
     */
    private Double dispatchAfter12HoursHasOrderRate;

    public static OperationReportRespVo empty() {
        return new OperationReportRespVo().nullData();
    }

    /**
     * 将所有属性设置为逻辑默认值（Integer为0，Double为0.00D），用于空数据初始化。
     *
     * @return OperationReportRespVo 当前对象
     */
    public OperationReportRespVo nullData() {
        try {
            // 明确指定操作当前类，防止子类干扰
            Class<?> clazz = OperationReportRespVo.class;
            Field[] fields = clazz.getDeclaredFields();
            Map<String, Method> setterMap = Arrays.stream(clazz.getDeclaredMethods())
                    .filter(method ->
                            method.getName().startsWith("set")
                                    && method.getParameterCount() == 1
                                    && (
                                    method.getParameterTypes()[0] == Integer.class
                                            || method.getParameterTypes()[0] == int.class
                                            || method.getParameterTypes()[0] == Double.class
                                            || method.getParameterTypes()[0] == String.class
                                            || method.getParameterTypes()[0] == Boolean.class
                                            || method.getParameterTypes()[0] == boolean.class
                                            || method.getParameterTypes()[0] == BigDecimal.class
                            )
                    )
                    .collect(Collectors.toMap(Method::getName, m -> m, (m1, m2) -> m1));

            for (Field field : fields) {
                String setterName = "set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                Method setter = setterMap.get(setterName);

                if (setter == null) {
                    continue;
                }

                // 统一处理为包装类型
                if (Integer.class.isAssignableFrom(field.getType()) || int.class == field.getType()) {
                    setter.invoke(this, 0);
                } else if (Double.class.isAssignableFrom(field.getType()) || double.class == field.getType()) {
                    setter.invoke(this, 0.00D);
                } else if (Boolean.class.isAssignableFrom(field.getType()) || boolean.class == field.getType()) {
                    setter.invoke(this, false);
                } else if (String.class == field.getType()) {
                    setter.invoke(this, "");
                } else if (BigDecimal.class == field.getType()) {
                    setter.invoke(this, BigDecimal.ZERO);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("初始化空数据失败", e);
        }
        return this;
    }

    /**
     * 设置关于用户操作车辆的字段，包括总扫码次数、总开锁次数、开锁成功次数、有效骑行次数、骑行失败次数。
     *
     * @param totalScanCodeCount 总扫码次数
     * @param totalUnlockCount   总开锁次数
     * @param successUnlockCount 开锁成功次数
     * @param validOrderCount    有效骑行次数
     */
    public void setAboutUserOpMachineField(Integer totalScanCodeCount,
                                           Integer totalUnlockCount,
                                           Integer successUnlockCount,
                                           Integer validOrderCount) {
        // 总扫码次数：orderanalysisstat . scanCodeCount
        // 总开锁次数：orderanalysisstat . unlockCount
        // 开锁成功次数：orderanalysisstat . successUnlockCount
        // 有效骑行次数：orderanalysisstat . validOrderCount
        // 骑行失败次数：总开锁次数 - 开锁成功次数
        this.setTotalScanCodeCount(totalScanCodeCount == null ? 0 : totalScanCodeCount)
                .setTotalUnlockCount(totalUnlockCount == null ? 0 : totalUnlockCount)
                .setSuccessUnlockCount(successUnlockCount == null ? 0 : successUnlockCount)
                .setValidOrderCount(validOrderCount == null ? 0 : validOrderCount)
                .setFailUnlockCount(this.getTotalUnlockCount() - this.getSuccessUnlockCount());
    }
}
